import axios, { AxiosRequestHeaders, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import { useUserStore } from "@/store/user";
import { useBootStore } from "@/store/boot";
import { useSimulateStore } from "@/store/simulate";
import { layer } from '@layui/layui-vue';
import router from '../router'
import qs from 'qs'
import {Result} from "@/types/result";

type TAxiosOption = {
    timeout: number;
    baseURL: string;
}

const loginRouteUrl = "/login";
 
const config: TAxiosOption = {
    timeout: 5000,
    baseURL: "http://127.0.0.1:8002"
}
 
class Http {
    service;
    constructor(config: TAxiosOption) {
        this.service = axios.create(config)
        // 处理传递数组报错问题
        this.service.defaults.paramsSerializer = function (params){
            // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) // 'a[0]=b&a[1]=c'
            // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })    // 'a[]=b&a[]=c'
            // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })  // 'a=b&a=c'
            // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })   // 'a=b,c'
            return qs.stringify(params, {arrayFormat: 'repeat', allowDots: true})
        }
        /* 请求拦截 */
        this.service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
            const userStore = useUserStore();
            const bootStore = useBootStore();
            const simulateStore = useSimulateStore();

            // 判断是否存在模拟登陆
            if (bootStore.simulate) {
                if (simulateStore.token){
                    (config.headers as AxiosRequestHeaders).satoken = simulateStore.token as string;
                }else {
                    // Promise.reject("模拟用户token不存在");
                    bootStore.clearSimulate()
                    layer.msg("模拟登录用户token不存在，转为正常登录", { icon : 2, time: 2000})
                    return Promise.reject("模拟用户token不存在");
                }
            }else {
                if (userStore.token) {
                    (config.headers as AxiosRequestHeaders).satoken = userStore.token as string;
                } else {
                    if(router.currentRoute.value.path !== loginRouteUrl) {
                        router.push({
                            path: loginRouteUrl,
                            query:{
                                back: router.currentRoute.value.path
                            }
                        });
                    }
                    // if(router.currentRoute.value.path !== '/login') {
                    //     router.push({path: '/login'})
                    // }
                }
            }
            return config
        }, error => {
            return Promise.reject(error);
        })

        /* 响应拦截 */
        this.service.interceptors.response.use(<T>(response: AxiosResponse<Result<T>>): AxiosResponse<Result<T>, any> => {
            const userStore = useUserStore();
            const bootStore = useBootStore();
            const simulateStore = useSimulateStore();
            switch (response.data.code) {
                case 401:
                    layer.confirm(
                        response.data.msg,
                        {
                            icon : 2,
                            yes: function(){
                                userStore.delAll();
                                simulateStore.delAll();
                                bootStore.clearSimulate()
                                router.push(loginRouteUrl);
                                layer.closeAll()
                            }
                        });
                    return response.data as any;
                case 200:
                    if (response.config.method !== 'get') {
                        layer.notify({
                            title: "success",
                            content: response.data.msg,
                            icon:1
                        })
                    }
                    return response.data as any;
                default:
                    layer.notify({
                        title: "error",
                        content: response.data.msg,
                        icon:2
                    })
                    return response.data as any;
            }
        }, error => {
            return Promise.reject(error)
        })
    }

    /* GET 方法 */
    get<T>(url: string, params?: object, _object = {}): Promise<Result<T>> {
        return this.service.get(url, { params, ..._object })
    }
    /* POST 方法 */
    post<T>(url: string, params?: object, _object = {}): Promise<Result<T>> {
        return this.service.post(url, params, _object)
    }
    /* PUT 方法 */
    put<T>(url: string, params?: object, _object = {}): Promise<Result<T>> {
        return this.service.put(url, params, _object)
    }
    /* DELETE 方法 */
    delete<T>(url: string, params?: any, _object = {}): Promise<Result<T>> {
        return this.service.delete(url, { params, ..._object })
    }
}

export default new Http(config)